﻿/// <reference path="./Scripts/typings/jquery/jquery.d.ts" />
/// <reference path="./Scripts/typings/signalr/signalr.d.ts" />
/// <reference path="./Scripts/typings/angularjs/angular.d.ts" />
/// <reference path="syncHub.ts" />

interface IShellController extends ng.IScope {
    isSyncAutomatic: boolean;
    errPolicy: string;
    currentDatabaseGroup: string;
    lastDatabaseGroup: string;
    nextAutoStart: string;
    lastSessionStatus: string;
    syncProgress: string;
    serviceStatus: string;
    skipCloning: string;
    machineName: string;

    syncCmd: any;
    cancelCmd: any;
    send: any;
    isConnected: boolean;
    isSynchronizing: boolean;
    isHubInactive: any;
    syncSteps: ISyncStep[];

    moveUp: (index: number) => void;
    moveDown: (index: number) => void;
    onConnected: any;
    currentSelected: any;
    toggleAllSyncSteps: (execute: boolean) => void;
}

class ShellController {
    constructor(private $scope: IShellController, $rootScope) {
        $scope.isSyncAutomatic = false;

        $scope.isConnected = false;

        $scope.errPolicy = "";
        $scope.lastSessionStatus = "";
        $scope.syncProgress = "";

        $scope.isHubInactive = function () {
            return !$scope.isConnected;
        };

        //Set the hubs URL for the connection
        $.connection.hub.url = "signalr";

        // Declare a proxy to reference the hub.
        var sync = $.connection.syncHub;

        // Create a function that the hub can call to broadcast messages.
        sync.client.addMessage = function (message) {
            // Html encode message.
            var encodedMsg = $('<div />').text(message).html();
            // Add the message to the page.
            $('#messages').append('<li>' + encodedMsg + '</li>');
            $('#messages').scrollTop($('#messages').prop("scrollHeight"));
        };

        sync.client.lastSessionStatus = function (param) {
            $scope.$apply(function () {
                $scope.lastSessionStatus = param;
            });
        };

        sync.client.progressChange = function (param) {
            $scope.$apply(function () {
                $scope.syncProgress = param;
            });
        };

        sync.client.isSyncAutomatic = function (param) {
            $scope.$apply(function () {
                $scope.isSyncAutomatic = param;
            });
        };
        sync.client.isSyncChange = function (param) {
            $scope.$apply(() => { $scope.isSynchronizing = param; });
        };
        sync.client.errorPolicy = function (param) {
            $scope.$apply(() => { $scope.errPolicy = param; });
        }
        sync.client.currentDatabaseGroup = function (param) {
            $scope.$apply(() => { $scope.currentDatabaseGroup = param; });
        }
        sync.client.lastDatabaseGroup = function (param) {
            $scope.$apply(() => { $scope.lastDatabaseGroup = param; });
        }

        sync.client.nextAutoStart = function (param) {
            $scope.$apply(() => { $scope.nextAutoStart = param; });
        }

        sync.client.serviceStatus = function (param) {
            $scope.$apply(() => { $scope.serviceStatus = param; });
        }

        sync.client.skipCloning = function (param) {
            $scope.$apply(() => { $scope.skipCloning = param; });
        }

        sync.client.machineName = function (param) {
            $scope.$apply(() => { $scope.machineName = param; });
        }

        // Start the connection.
        $.connection.hub.start()
            .done(function () {
                $scope.onConnected();
            })
            .fail(function () {
                var encodedMsg = $('<div />').text("SignalR failed to initialize!").html();
                // Add the message to the page.
                $('#messages').append('<li>' + encodedMsg + '</li>');
            });

        $.connection.hub.reconnected($scope.onConnected);

        $scope.onConnected = function onConnected() {
            $scope.$apply(function () {
                $scope.isConnected = true;
            });

            sync.server.getSyncSteps().done((response) => {
                $scope.$apply(function () {
                    $scope.syncSteps = response.Items.sort((a, b) => {
                        return a.ExecutionOrder - b.ExecutionOrder;
                    });
                });
            });

            sync.server.isSynchronizing().done((response) => {
                $scope.$apply(s => $scope.isSynchronizing = response);
            });

            sync.server.getState().done((response) => {
                $('#messages').empty();

                if (!response || !response.State) {
                    return;
                }
                $scope.$apply(function () {
                    $scope.syncProgress = response.State.Progress;
                    $scope.lastSessionStatus = response.State.Status;
                    $scope.serviceStatus = response.State.ServiceStatus
                });

                if (response.State.Messages) {
                    response.State.Messages.forEach((message) => {
                        var encodedMsg = $('<div />').text(message).html();
                        // Add the message to the page.
                        $('#messages').append('<li>' + encodedMsg + '</li>');
                    });
                    $('#messages').scrollTop($('#messages').prop("scrollHeight"));
                }
            });
        }

        $scope.syncCmd = () => {
            if ($scope.isSynchronizing) return;
            $('#messages').empty();
            sync.server.startManualSync($scope.syncSteps);
            // Clear text box and reset focus for next comment.
            $('#messages').val('').focus();
        };

        $scope.cancelCmd = () => {
            sync.server.cancelSync();
        };

        $scope.send = () => {
            sync.server.send($('#message').val());
            // Clear text box and reset focus for next comment.
            $('#message').val('');
        };

        $scope.moveUp = (index: number) => {
            if ($scope.currentSelected) {
                $scope.currentSelected.selected = false;
            }

            if (index > 0) {
                var previous = $scope.syncSteps[index - 1];
                var current = $scope.syncSteps[index];

                var currentOrder = current.ExecutionOrder;
                current.ExecutionOrder = previous.ExecutionOrder;
                previous.ExecutionOrder = currentOrder;

                $scope.currentSelected = current;
                if ($scope.currentSelected) {
                    $scope.currentSelected.selected = true;
                }

                $scope.syncSteps[index - 1] = current;
                $scope.syncSteps[index] = previous;
            }
        };

        $scope.moveDown = (index: number) => {
            if ($scope.currentSelected) {
                $scope.currentSelected.selected = false;
            }
            if (index < $scope.syncSteps.length - 1) {
                var next = $scope.syncSteps[index + 1];
                var current = $scope.syncSteps[index];
                $scope.currentSelected = current;
                if ($scope.currentSelected) {
                    $scope.currentSelected.selected = true;
                }

                var currentOrder = current.ExecutionOrder;
                current.ExecutionOrder = next.ExecutionOrder;
                next.ExecutionOrder = currentOrder;

                $scope.syncSteps[index + 1] = current;
                $scope.syncSteps[index] = next;
            }
        };

        $scope.toggleAllSyncSteps = (execute: boolean) => $scope.syncSteps.forEach(item => item.Execute = execute);
    }
}

var controllerId = 'shell';

angular.module('app').controller(controllerId, ['$scope', '$rootScope', ($scope, $rootScope) =>
    new ShellController($scope, $rootScope)
]);
